package org.finesys.common.netty.websocket.support;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.cors.CorsConfig;
import io.netty.handler.codec.http.cors.CorsConfigBuilder;
import io.netty.handler.codec.http.cors.CorsHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.concurrent.EventExecutorGroup;
import org.finesys.common.netty.websocket.handler.HttpServerHandler;
import org.finesys.common.netty.websocket.util.SslUtils;
import org.springframework.util.ObjectUtils;

import javax.net.ssl.SSLException;
import java.util.Arrays;

import static org.finesys.common.netty.websocket.constants.WebConfigConstant.MAX_FRAME_SIZE;

/**
 * WebSocket服务器管理类，创建websocket服务和优雅的关闭服务
 */
public class WebSocketInitializer extends ChannelInitializer<Channel> {

    private final WebSocketEndpointEventServer webSocketEndpointEventServer;
    private final WebSocketEndpointConfig webSocketEndpointConfig;
    private final EventExecutorGroup eventExecutorGroup;

    private SslContext sslContext;
    private CorsConfig corsConfig;

    public WebSocketInitializer(WebSocketEndpointEventServer webSocketEndpointEventServer, WebSocketEndpointConfig webSocketEndpointConfig, EventExecutorGroup eventExecutorGroup) throws SSLException {
        this.webSocketEndpointEventServer = webSocketEndpointEventServer;
        this.webSocketEndpointConfig = webSocketEndpointConfig;
        this.eventExecutorGroup = eventExecutorGroup;
        init();
    }

    private void init() throws SSLException {
        // SSL配置
        if (!ObjectUtils.isEmpty(webSocketEndpointConfig.getKeyStore())) {
            // 创建SSL上下文
            sslContext = SslUtils.createSslContext(webSocketEndpointConfig.getKeyPassword(), webSocketEndpointConfig.getKeyStore(), webSocketEndpointConfig.getKeyStoreType(), webSocketEndpointConfig.getKeyStorePassword(), webSocketEndpointConfig.getTrustStore(), webSocketEndpointConfig.getTrustStoreType(), webSocketEndpointConfig.getTrustStorePassword());
        } else {
            // 如果没有配置KeyStore，则SSL上下文为空
            sslContext = null;
        }
        // 跨域配置
        corsConfig = createCorsConfig(webSocketEndpointConfig.getCorsOrigins(), webSocketEndpointConfig.getCorsAllowCredentials());
    }

    /**
     * 创建跨域请求配置
     */
    private CorsConfig createCorsConfig(String[] corsOrigins, Boolean corsAllowCredentials) {
        // 如果corsOrigins数组为空，则返回null
        if (ObjectUtils.isEmpty(corsOrigins)) {
            return null;
        }
        // 根据corsOrigins数组的内容创建CorsConfigBuilder对象
        // 如果corsOrigins中包含"*"，则使用CorsConfigBuilder.forAnyOrigin()
        // 否则，使用CorsConfigBuilder.forOrigins(corsOrigins)
        CorsConfigBuilder corsConfigBuilder = Arrays.stream(corsOrigins).anyMatch("*"::equals) ? CorsConfigBuilder.forAnyOrigin() : CorsConfigBuilder.forOrigins(corsOrigins);
        // 如果corsAllowCredentials不为null且为true，则允许发送credentials
        if (corsAllowCredentials != null && corsAllowCredentials) {
            corsConfigBuilder.allowCredentials();
        }
        // 允许空来源
        corsConfigBuilder.allowNullOrigin();
        // 构建并返回CorsConfig对象
        return corsConfigBuilder.build();
    }

    @Override
    protected void initChannel(Channel channel) throws Exception {
        // 获取当前Channel的Pipeline
        ChannelPipeline pipeline = channel.pipeline();
        // 如果配置了SSL，则添加SSL处理器
        if (sslContext != null) {
            pipeline.addFirst(sslContext.newHandler(channel.alloc()));
        }
        // 添加HTTP编解码器
        pipeline.addLast(new HttpServerCodec());
        // 添加HTTP对象聚合器，设置最大消息大小为65536字节
        pipeline.addLast(new HttpObjectAggregator(MAX_FRAME_SIZE.getValue()));
        // 添加分块写处理器
        pipeline.addLast(new ChunkedWriteHandler());
        // 如果配置了跨域，则添加跨域处理器
        if (corsConfig != null) {
            pipeline.addLast(new CorsHandler(corsConfig));
        }
        //启用Http协议支持
        // 添加自定义的HTTP服务器处理器
        pipeline.addLast(new HttpServerHandler(webSocketEndpointEventServer, // WebSocket事件服务器
                webSocketEndpointConfig, // WebSocket端点配置
                eventExecutorGroup, // EventExecutorGroup（如果配置）
                corsConfig != null // 是否启用了跨域
        ));
    }
}
